﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace WordpressRestApi
{
    /// <summary>Entry point for the Wordpress API.</summary>
    public class WordpressClient
    {
        /// <summary>Construct a client from a token.</summary>
        /// <param name="token">Token.</param>
        public WordpressClient(TokenInfo token)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }
            if (string.IsNullOrWhiteSpace(token.AccessToken))
            {
                throw new ArgumentNullException("token.AccessToken");
            }
            if (string.IsNullOrWhiteSpace(token.BlogID))
            {
                throw new ArgumentNullException("token.BlogID");
            }
            if (string.IsNullOrWhiteSpace(token.BlogUrl))
            {
                throw new ArgumentNullException("token.BlogUrl");
            }

            Token = token;
            User = new UserClient(Token);
            Site = new SiteClient(Token);
            Post = new PostClient(Token);
            Tag = new TagClient(Token);
        }

        /// <summary>Token package.</summary>
        public TokenInfo Token { get; }

        /// <summary>User client.</summary>
        public UserClient User { get; }

        /// <summary>Site client.</summary>
        public SiteClient Site { get; }

        /// <summary>Post client.</summary>
        public PostClient Post { get; }

        /// <summary>Tag client.</summary>
        public TagClient Tag { get; }

        #region Authentication
        /// <summary>Returns the URL to send the user to in order to authorize the application.</summary>
        /// <param name="appClientID">Client-ID of the Wordpress application.</param>
        /// <param name="returnUrl">Return URL Wordpress will return the user to, posting its code.</param>
        /// <returns></returns>
        public static string GetUserAuthorizeUrl(string appClientID, string returnUrl)
        {
            return "https://public-api.wordpress.com/oauth2/authorize?client_id="
                + appClientID
                + "&redirect_uri="
                + returnUrl
                + "&response_type=code";
        }

        /// <summary>Acquires the token from the Wordpress Token service.</summary>
        /// <param name="clientID"></param>
        /// <param name="clientSecret"></param>
        /// <param name="redirectURL"></param>
        /// <param name="code">Temporary code returned by Wordpress authentication page.</param>
        /// <returns>Client.</returns>
        public static async Task<WordpressClient> GetTokenAsync(
            string clientID, string clientSecret, string redirectURL, string code)
        {
            if (string.IsNullOrWhiteSpace(clientID))
            {
                throw new ArgumentNullException("clientID");
            }
            if (string.IsNullOrWhiteSpace(clientSecret))
            {
                throw new ArgumentNullException("clientSecret");
            }
            if (string.IsNullOrWhiteSpace(redirectURL))
            {
                throw new ArgumentNullException("redirectURL");
            }
            if (string.IsNullOrWhiteSpace(code))
            {
                throw new ArgumentNullException("code");
            }
            using (var client = new HttpClient())
            {
                var pairs = new[]
                {
                    new KeyValuePair<string, string>("client_id",clientID),
                    new KeyValuePair<string, string>("redirect_uri",redirectURL),
                    new KeyValuePair<string, string>("client_secret",clientSecret),
                    new KeyValuePair<string, string>("code",code),
                    new KeyValuePair<string, string>("grant_type","authorization_code")
                };
                var httpContent = new FormUrlEncodedContent(pairs);
                var response = await client.PostAsync("https://public-api.wordpress.com/oauth2/token", httpContent);
                var json = await response.Content.ReadAsStringAsync();
                var token = JsonConvert.DeserializeObject<TokenInfo>(json);

                if (token == null
                    || string.IsNullOrWhiteSpace(token.AccessToken)
                    || string.IsNullOrWhiteSpace(token.BlogID)
                    || string.IsNullOrWhiteSpace(token.BlogUrl))
                {
                    throw new UnauthorizedAccessException("Returned token is invalid:  " + json);
                }

                return new WordpressClient(token);
            }
        }
        #endregion
    }
}